package gameComponents;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Tablero {
	
	private ZonaTablero zonaNorte;
	private ZonaTablero zonaSur;
	private int ancho;
	private int alto;
	private int cantJugadores;
	private List<Tesoro> tesoros;
	
	// Getters and Setters
	
	
	
	public ZonaTablero getZonaNorte() {
		return zonaNorte;
	}
	public int getCantJugadores() {
		return cantJugadores;
	}
	public void setCantJugadores(int cantJugadores) {
		this.cantJugadores = cantJugadores;
	}
	public void setZonaNorte(ZonaTablero zonaNorte) {
		this.zonaNorte = zonaNorte;
	}
	public ZonaTablero getZonaSur() {
		return zonaSur;
	}
	public void setZonaSur(ZonaTablero zonaSur) {
		this.zonaSur = zonaSur;
	}
	public int getAncho() {
		return ancho;
	}
	public void setAncho(int ancho) {
		this.ancho = ancho;
	}
	public int getAlto() {
		return alto;
	}
	public void setAlto(int alto) {
		this.alto = alto;
	}
	public List<Tesoro> getTesoros() {
		return tesoros;
	}
	public void setTesoros(List<Tesoro> tesoros) {
		this.tesoros = tesoros;
	}
	
	public int alto(){
		return (this.getZonaNorte().getFilas().size() + this.getZonaSur().getFilas().size() );
	}
	
	// Constructor 
	
	public Tablero(int ancho, int alto){
		this.setAlto(alto);
		this.setAncho(ancho);
		this.setCantJugadores(this.getAlto()/2);
		this.setZonaNorte(new ZonaTablero(this.getAncho(),(this.getAlto()/2) + 1));
		this.setZonaSur(new ZonaTablero(this.getAncho(),this.getAlto()/2));
		this.getZonaSur().cambiarNumerosDeFila((this.getAlto()/2));
		this.setTesoros(new ArrayList<Tesoro>());
		this.generarTesoros(this.getCantJugadores());
		this.getZonaSur().cambiarNumerosDeFila(this.getAlto() / 2);
	}
	
	// Utils para buscar Celda
	
		public Celda celdaEn(int x, int y){
			if(y > (this.getAlto()/2)){
				return (this.getZonaSur().celdaEn(x,(y-(this.getAlto()/2)-1)));
			}else{
				return (this.getZonaNorte().celdaEn(x,y));
			}
		}
	
	
	//Generar Tesoros, deben ser tantos como jugadores haya.
	
	public void generarTesoros(int cantTesoros){
		
		while(this.getTesoros().size() <= cantTesoros){
			
			Random r1 = new Random();
			Random r2 = new Random();
			
			int rx1 = this.generarXValido(r1);
			int ry1 = this.generarYValido(r2);
			int rx2 = this.generarXValido(r1);
			int ry2 = this.generarYValido(r2);
			
			Tesoro t1 = new Tesoro("EquipoArriba", this.celdaEn(rx1, ry1));
			Tesoro t2 = new Tesoro("EquipoAbajo", this.celdaEn(rx2, ry2));
			
			if(!this.hayTesoroEnCelda(this.celdaEn(rx1, ry1)) && !this.hayTesoroEnCelda(this.celdaEn(rx2, ry2))){
				this.getTesoros().add(t1);
				this.getTesoros().add(t2);
			}
		}
	}
	
	public int generarXValido(Random r){
		int ret = r.nextInt(this.getAncho());
		while(ret == 0 || ret == this.getAncho()-1){
			 ret = r.nextInt(this.getAncho());
		}
		return ret;
	}
	
	public int generarYValido(Random r){
		int ret = r.nextInt(this.getAlto());
		while( ret == this.getAlto()/2 || (ret == 0 || ret == this.alto()-1)){
			 ret = r.nextInt(this.getAlto());
			 
		}
		return ret;
	}
	
	public int tesorosRestantesEquipo(String equipo){
		int ret = 0;
		
		for(Tesoro each : this.getTesoros()){
			if(each.getEquipo().equals(equipo)){
				ret = ret + 1;
			}
		}
		return ret;
	}
	
	public boolean terminoJuego(){
		return (this.tesorosRestantesEquipo("EquipoArriba") == 0 || this.tesorosRestantesEquipo("EquipoAbajo") == 0);
	}
	
	
	
	// Utils para generar Tesoros
	
//	public void generarTesoros(int cant){
//		for(int i = 0 ; i < cant ; i++){
//			if(i < cant/2){
//				Tesoro t = new Tesoro("EquipoArriba", this.generarCelda());
//				this.getTesoros().add(t);
//			}
//			else{
//				Tesoro t = new Tesoro("EquipoAbajo", this.generarCelda());
//				this.getTesoros().add(t);
//			}
//		}
//	}
	
	/// MIRAR!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	public Celda generarCelda(){
		int random  = (int) (Math.random()*10);
		Celda c = null;
		if(random < 5){
			c = this.getZonaNorte().buscarCeldaRandom();
			
		}
		else{
			c = this.getZonaSur().buscarCeldaRandom();
		}
		if (c.getY() == this.getAlto()/2 -1){
			return this.generarCelda();
		}
		return c;
	}
	
	
	
	// Operaciones del monitor
	
	public synchronized void moverHorizontal(Jugador j, int numb) throws InterruptedException{
		while(!this.puedeMoverHorizontal(j, numb)){
			wait();
		}
		Celda celda = this.celdaEn(j.getCeldaActual().getX() + numb, j.getCeldaActual().getY());
		boolean hayTesoro = this.hayTesoroMioEnCelda(celda, j);
		j.mover(hayTesoro, celda);
	}
	
	public synchronized void moverVertical(Jugador j, int numb) throws InterruptedException{
		while(!this.puedeMoverAdelante(j, numb)){
			wait();
		}
		Celda celda = this.celdaEn(j.getCeldaActual().getX(), j.getCeldaActual().getY()+ numb);
		boolean hayTesoro = this.hayTesoroMioEnCelda(celda , j);
		j.mover(hayTesoro, celda);
		notifyAll();
	}
	
	// Utils para saber si se puede mover
	
	public boolean puedeMoverHorizontal(Jugador j, int numb){
		Celda c = this.celdaEn(j.getCeldaActual().getX()+ numb, j.getCeldaActual().getY());
		return j.getCeldaActual().getX()>0 &&
			   j.getCeldaActual().getX() < this.getAncho() &&
			   !c.isOcupada() &&
			   ! terminoJuego()
			   ;
	}
	
	private boolean puedeMoverAdelante(Jugador j, int i) {
		//Celda c = this.celdaEn(j.getCeldaActual().getX(), j.getCeldaActual().getY()+ i);
		return 
//				j.getCeldaActual().getY()>0 && 
//			   j.getCeldaActual().getY() < this.getAlto() &&
			 //  !c.isOcupada()&&
			   ! terminoJuego() && tieneVecino(j)
			   ;
	}
	
	private boolean tieneVecino(Jugador j){
		return this.chequearDerecha(j.getCeldaActual(), j.getEquipo()) || this.chequearIzquierda(j.getCeldaActual(), j.getEquipo()) || this.chequearAbajo(j);
	}

	private boolean chequearDerecha(Celda celda, String equipo){
		if(celda.getX() != this.getAncho()-1){
			Celda aux =this.celdaEn(celda.getX()+1, celda.getY());
			if(!aux.isOcupada()){return false;}
			return aux.getJugador().getEquipo() == equipo;
		}
		return false;
	}
	
	private boolean chequearIzquierda(Celda celda, String equipo){
		if(celda.getX() != 0){
			Celda aux =this.celdaEn(celda.getX()-1, celda.getY());
			if(!aux.isOcupada()){return false;}
			return aux.getJugador().getEquipo() == equipo;
		}
		return false;
	}
	
	private boolean chequearAbajo(Jugador j){
		boolean b = false;
		if(j.getEquipo() == "EquipoArriba"){
			if(j.getCeldaActual().getY() != this.getAlto()-1){
				Celda aux = this.celdaEn(j.getCeldaActual().getX(), j.getCeldaActual().getY()+1);
				if(aux.isOcupada()){
					if(aux.getJugador().getEquipo() == j.getEquipo()){b = true;}
				}
				return b || this.chequearIzquierda(aux, j.getEquipo()) || this.chequearDerecha(aux, j.getEquipo());
			}
			return b;
		}
		else{
			if(j.getCeldaActual().getY() != 0){
				Celda aux = this.celdaEn(j.getCeldaActual().getX(), j.getCeldaActual().getY()-1);
				if(aux.isOcupada()){
					if(aux.getJugador().getEquipo() == j.getEquipo()){b = true;}
				}
				return b || this.chequearIzquierda(aux, j.getEquipo()) || this.chequearDerecha(aux, j.getEquipo());
			}
			return b;
		}
	}
	
	public Tesoro tesoroDeCelda(int x, int y){
		return this.celdaEn(x, y).getTesoro();
	}
	
	
	public boolean hayTesoroEnCelda(Celda c){
		for(Tesoro tesoro : this.getTesoros()){
			if(tesoro.getCeldaActual().esIgual(c)){
				c.setTesoro(tesoro);
				return true;
			}
		}
		return false;
	}

	public boolean hayTesoroMioEnCelda(Celda c, Jugador j){
		for(Tesoro tesoro : this.getTesoros()){
			if(tesoro.getCeldaActual().esIgual(c)){
				return (tesoro.getEquipo() == j.getEquipo());
			}
		}
		return false;
	}

	public static void main(String[] args) {
		Tablero t = new Tablero(11, 11);
		System.out.println(t.alto());
		System.out.println(t.getAlto());
		System.out.println(t.getAncho());
		System.out.println(t.getZonaNorte().getFilas().size());
		System.out.println(t.getZonaSur().getFilas().size());
		System.out.println(t.getZonaNorte().getFilas().get(0).getCeldas().size());
		for(Tesoro r : t.getTesoros()){
			System.out.println("TESOROS = " + r.getEquipo() + "Celda = " + "("+r.getCeldaActual().getX()+ ","+ r.getCeldaActual().getY()+")");
		}
		
		ArrayList<Movimiento> movs1 = new ArrayList<Movimiento>();
		ArrayList<Movimiento> movs2 = new ArrayList<Movimiento>();
		ArrayList<Movimiento> movs3 = new ArrayList<Movimiento>();
		ArrayList<Movimiento> movs4 = new ArrayList<Movimiento>();
		
		movs1.add(new Adelante(t));
		movs1.add(new Izquierda(t));
		movs1.add(new Derecha(t));
		movs1.add(new Adelante(t));
		movs1.add(new Izquierda(t));
		movs1.add(new Derecha(t));
		
		movs2.add(new Adelante(t));
		movs2.add(new Adelante(t));
		movs2.add(new Izquierda(t));
		movs2.add(new Derecha(t));
		
		movs3.add(new Adelante(t));
		movs3.add(new Derecha(t));
		movs3.add(new Izquierda(t));
		movs3.add(new Derecha(t));
		movs3.add(new Adelante(t));
		movs3.add(new Adelante(t));
		
		
		movs4.add(new Adelante(t));
		movs4.add(new Derecha(t));
		movs4.add(new Izquierda(t));
		movs4.add(new Derecha(t));
		
		Celda celdaInicial1 = t.celdaEn(2, 2);
		System.out.println("Jugador 1 = POSACTUAL (2,2)");
		Celda celdaInicial2 = t.celdaEn(3, 2);
		System.out.println("Jugador 2 = POSACTUAL (3,1)");
		Celda celdaInicial3 = t.celdaEn(1, 7);
		System.out.println("Jugador 3 = POSACTUAL (1,7)");
		Celda celdaInicial4 = t.celdaEn(7, 9);
		System.out.println("Jugador 4 = POSACTUAL (7,9)");
		
		Jugador jugador1 = new Jugador("Jugador1","EquipoArriba", celdaInicial1, movs1);
		Jugador jugador2 = new Jugador("Jugador2","EquipoArriba", celdaInicial2, movs2);
		Jugador jugador3 = new Jugador("Jugador3","EquipoAbajo", celdaInicial3, movs3);
		Jugador jugador4 = new Jugador("Jugador4","EquipoAbajo", celdaInicial4, movs4);
		
		jugador3.start();
		jugador4.start();
		jugador1.start();
		jugador2.start();
		
		
//		for(Celda c : t.getZonaNorte().getFilas().get(5).getCeldas()){
//			System.out.println(c.getX()+","+c.getY());
//		}
//		
//		for(Celda c : t.getZonaSur().getFilas().get(4).getCeldas()){
//			System.out.println(c.getX()+","+c.getY());
//		}

	}
	
}
